#include <extractGraph/extractGraph.h>
#include <multipleImage/multipleImage.h>
#include <opencv2/xfeatures2d/nonfree.hpp>
#include <opencv2/opencv.hpp>

using namespace xfeatures2d;

Mat sourceImg = imread("../../resource/image/circult/image3.jpg");
UnderTestElectronics underTestEles(sourceImg);
/*对样本库中的器件进行信息建立, 包括该样本的名称、接线数字、电气参数*/
/*邻接矩阵使用大小为linesRect.size * cellsRect.size的矩阵*/
vector<vector<bool>> adjMat(underTestEles.linesRect.size(),
                              vector<bool>(underTestEles.cellsRect.size(), false));
/*邻接表有cellsRect.size个，其中的节点信息包括：
    编号
    已经配到到的名称*/
/*邻接表中的每个开始节点按照矩阵方位，
 * 从左上--右上--下一行的左上--下一行的右上进行排序，*/
typedef struct    //电路线信息
{
    int lineNo;     //线编号
    int lineLength; //线长度
    double linePos; //线角度
} LineInfoNode;

//元件电气属性
typedef struct  //元件电气属性(后期可能会用到)
{
    String cellDetailName; //元件名，例如PNP的2N3904
    String cellPackageType;//元件封装类型 例如TO-220和SOT-23
    String cellManucator;  //元件生产厂商
} ElectricalInfo;

typedef struct CellNode    //元件信息
{
    int cellNo = INFINITY;     //元件编号
    String cellType = "";       //元件类型 例如PNP，Res
    Rect cellSite = Rect();     //元件位置
    ElectricalInfo electricalInfo;  //元件的电气属性
    CellNode* nextCell = NULL; //通过指针指向下一个元件
    //构造函数
    CellNode()
    {
    }
    CellNode(int cell_no) : cellNo(cell_no)
    {
        cellType = "";
    }
    CellNode(int cell_no, String cell_type) :
        cellNo(cell_no), cellType(cell_type)
    {

    }
    CellNode(int cell_no, String cell_type, ElectricalInfo electrical_info) :
        cellNo(cell_no), cellType(cell_type), electricalInfo(electrical_info)
    {

    }
} CellNode;

vector<CellNode*> cellsTable(underTestEles.cellsCount, new CellNode());  //电路图邻接表(指针类型)

int main()
{
//    imshow("sourceImg", sourceImg); //显示源图
//    imshow("sourceBinnayImg", underTestEles.sourceBinnaryImg);  //显示灰度源图
//    underTestEles.showComponentImg();
//    underTestEles.showCellsImg();
//    underTestEles.showCellAndRectImg();
//    underTestEles.showLinesAndRectImg();

/*进行数据处理，利用提取到的器件矩形轮廓与线路矩形轮廓进行相交
1.如果器件矩形与线路矩形相交，则判定器件与线路之间可以连接。
2.对于两个器件矩形轮廓相交与同一个线路，而彼此本身不想交，则两者之间具有连接关系(图的互通)
*/
    //先使用图的邻接矩阵法求出各个cell与line的连线
    for (size_t eachCell=0; eachCell<underTestEles.cellsRect.size(); eachCell++)
    {
        for (size_t eachLine=0; eachLine<underTestEles.linesRect.size(); eachLine++)
        {
            /*判断eachCellRect是否与eachLineRect矩形相交，如果相交，则将邻接矩阵的
           值改为true，否则为false
            */
            Rect rectIntersection = underTestEles.cellsRect[eachCell] &
                    underTestEles.linesRect[eachLine];  //交集矩阵
            if (rectIntersection.area() != 0)
                adjMat[eachLine][eachCell] = true;
        }
    }
    cout << "连线结果图: " << endl;
    for (auto rows : adjMat)
    {
        for (auto cols : rows)
        {
            cout << cols << " ";
        }
        cout << endl;
    }
    //后对整个邻接矩阵进行遍历, 得到图的邻接表
    cout << "建立邻接表..." << endl;
    for (int eachCell=0; eachCell<underTestEles.cellsCount; eachCell++)
    {
        cellsTable[eachCell]->cellNo = eachCell;    //元件编号录入
        CellNode* tempNode = new CellNode();
        tempNode = cellsTable[eachCell];            //临时节点接入主节点

        cout << cellsTable[eachCell]->cellNo << "->";
        for (size_t eachLine=0; eachLine<underTestEles.linesRect.size(); eachLine++)
        {
            if (adjMat[eachLine][eachCell] == true)
            {
                //对eachCell的eachLine进行检索，检查是否存在与当前eachCell同一个eachLine的情况
                for (int i=0; i<underTestEles.cellsCount; i++)
                {
                    if (i == eachCell)
                        continue;
                    else if (adjMat[eachLine][i] == true)
                    {
                        //使用含参构造函数添加其cellNo和type
                        CellNode* cellInfoNode = new CellNode(i, "");
                        tempNode->nextCell = cellInfoNode;
                        tempNode = tempNode->nextCell;
                        cout << tempNode->cellNo << "->";
                    }
                }
            }
        }
        cout << endl;
    }
    //打印邻接表信息
//    cout << "打印邻接表信息..." << endl;
//    for (int eachCell=0; eachCell<underTestEles.cellsCount; eachCell++)
//    {
//        CellNode* tempNode = new CellNode();
//        tempNode = cellsTable[eachCell];
////        while (tempNode->nextCell != NULL)
////        {
////            cout << tempNode->cellNo << " " << endl;
////        }
////        cout << cellsTable[eachCell]->cellNo;
//        cout << endl;
//    }

    //显示
    waitKey(0);
    destroyAllWindows();
    return 0;
}
